﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace pngpacker
{
	public static class ImageWorker
	{
		public enum MergeOption
		{
			Horizontal = 0,
			Vertical = 1,
			Transparent = 2,
			MaxSize = 4
		}

		private delegate int int_func_image(Image i);

		private static int max(Image[] images, int_func_image f)
		{
			if (images == null || images.Length == 0)
				throw new ArgumentNullException();
			int maxValue = int.MinValue;
			foreach (Image i in images)
			{
				int t = f(i);
				if (t > maxValue)
					maxValue = t;
			}
			return maxValue;
		}

		private static int getWidth(Image i)
		{
			return i.Width;
		}

		private static int getHeight(Image i)
		{
			return i.Height;
		}

		private static int sum(Image[] images, int_func_image f)
		{
			if (images == null || images.Length == 0)
				throw new ArgumentNullException();
			int sumValue = 0;
			foreach (Image i in images)
			{
				sumValue += f(i);
			}
			return sumValue;
		}

		public static Bitmap Merge(Image[] images, MergeOption option)
		{
			Bitmap bitmap = null;
			int width = 0;
			int height = 0;
			bool optionHorizontal = ((option & MergeOption.Vertical) == 0);
			bool optionTransparent = ((option & MergeOption.Transparent) != 0);
			bool optionMaxSize = ((option & MergeOption.MaxSize) != 0);
			int maxWidth = 0;
			int maxHeight = 0;
			maxWidth = max(images, getWidth);
			maxHeight = max(images, getHeight);
			if (optionHorizontal)
			{
				height = maxHeight;
				if (optionMaxSize)
				{
					width = maxWidth * images.Length;
				}
				else
					width = sum(images, getWidth);
			}
			else
			{
				width = maxWidth;
				if (optionMaxSize)
					height = maxHeight * images.Length;
				else
					height = sum(images, getHeight);
			}
			bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
			if (optionTransparent)
				bitmap.MakeTransparent();
			using (Graphics g = Graphics.FromImage(bitmap))
			{
				if (!optionTransparent)
					g.Clear(Color.White);
				Rectangle rect = Rectangle.Empty;
				int position = 0;
				foreach (Image image in images)
				{
					rect.Width = image.Width;
					rect.Height = image.Height;
					if (optionMaxSize)
					{
						if (optionHorizontal)
						{
							rect.X = position + (maxWidth - rect.Width) / 2;
							rect.Y = (maxHeight - rect.Height) / 2;
						}
						else
						{
							rect.X = (maxWidth - rect.Width) / 2;
							rect.Y = position + (maxHeight - rect.Height) / 2;
						}
					}
					else
					{
						if (optionHorizontal)
						{
							rect.X = position;
						}
						else
						{
							rect.Y = position;
						}
					}
					g.DrawImageUnscaledAndClipped(image, rect);
					if (optionHorizontal)
					{
						position += (optionMaxSize? maxWidth :image.Width);
					}
					else
					{
						position += (optionMaxSize? maxHeight :image.Height);
					}
				}
			}
			return bitmap;
		}
	}
}
